package com.smart.community.work.controller;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.work.dto.LeaveQueryDTO;
import com.smart.community.work.entity.Leave;
import com.smart.community.work.service.LeaveService;
import com.smart.community.work.vo.LeaveVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 请假管理控制器
 * 
 * 严格按照《Java后端SpringBoot代码开发规范_重构版.md》Controller规范实现：
 * - 统一返回格式：使用Result统一包装返回结果
 * - 参数验证：使用@Valid注解进行参数验证
 * - 异常处理：使用统一的异常处理机制，异常往外抛
 * - 日志记录：记录关键操作日志，避免Controller层log.error
 * - 权限控制：使用SecurityUtils获取当前用户信息
 * - 完整注释：所有接口都有完整的Swagger文档注释
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/work/leave")
@RequiredArgsConstructor
@Validated
@Tag(name = "请假管理", description = "请假管理相关接口")
public class LeaveController {

    private final LeaveService leaveService;

    @GetMapping("/page")
    @Operation(summary = "分页查询请假记录", description = "分页查询请假记录列表，支持数据权限控制")
    public Result<IPage<LeaveVO>> selectLeavePage(
            @Parameter(description = "分页参数") Page<LeaveVO> page, 
            @Parameter(description = "查询参数") @ModelAttribute LeaveQueryDTO queryDTO) throws Exception {
        log.info("开始分页查询请假记录，当前页：{}，每页大小：{}，查询参数：{}", page.getCurrent(), page.getSize(), queryDTO);
        
        // 获取当前登录用户ID
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        IPage<LeaveVO> result = leaveService.selectLeavePageWithPermission(page, queryDTO, currentUserId);
        log.info("分页查询请假记录成功，返回记录数：{}", result.getRecords().size());
        return Result.success("查询成功", result);
    }

    @GetMapping("/{id}")
    @Operation(summary = "获取请假详情", description = "根据ID获取请假记录详情")
    public Result<LeaveVO> getLeaveDetail(
            @Parameter(description = "请假记录ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("开始获取请假详情，ID：{}", id);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("请假记录ID必须大于0");
        }
        
        // 获取当前登录用户ID
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        LeaveVO result = leaveService.getLeaveDetail(id, currentUserId);
        if (result == null) {
            return Result.fail("请假记录不存在或您无权查看");
        }
        
        log.info("获取请假详情成功，ID：{}", id);
        return Result.success("查询成功", result);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "根据用户ID查询请假记录", description = "根据用户ID查询请假记录")
    public Result<List<LeaveVO>> selectByUserId(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotNull Long userId, 
            @Parameter(description = "物业公司ID", required = true) @RequestParam @NotNull Long propertyCompanyId) throws Exception {
        log.info("开始根据用户ID查询请假记录，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        // 参数校验
        if (userId == null || userId <= 0) {
            return Result.fail("用户ID必须大于0");
        }
        if (propertyCompanyId == null || propertyCompanyId <= 0) {
            return Result.fail("物业公司ID必须大于0");
        }
        
        List<LeaveVO> result = leaveService.selectByUserId(userId, propertyCompanyId);
        log.info("根据用户ID查询请假记录成功，返回记录数：{}", result.size());
        return Result.success("查询成功", result);
    }

    @GetMapping("/pending/{approverId}")
    @Operation(summary = "根据审批人ID查询待审批请假记录", description = "根据审批人ID查询待审批请假记录")
    public Result<List<LeaveVO>> selectPendingByApproverId(
            @Parameter(description = "审批人ID", required = true) @PathVariable @NotNull Long approverId, 
            @Parameter(description = "物业公司ID", required = true) @RequestParam @NotNull Long propertyCompanyId) throws Exception {
        log.info("开始根据审批人ID查询待审批请假记录，审批人ID：{}，物业公司ID：{}", approverId, propertyCompanyId);
        
        // 参数校验
        if (approverId == null || approverId <= 0) {
            return Result.fail("审批人ID必须大于0");
        }
        if (propertyCompanyId == null || propertyCompanyId <= 0) {
            return Result.fail("物业公司ID必须大于0");
        }
        
        List<LeaveVO> result = leaveService.selectPendingByApproverId(approverId, propertyCompanyId);
        log.info("根据审批人ID查询待审批请假记录成功，返回记录数：{}", result.size());
        return Result.success("查询成功", result);
    }

    @ApiLog(
        logTitle = "申请请假",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/apply")
    @Operation(summary = "申请请假", description = "申请请假")
    public Result<Boolean> applyLeave(@Parameter(description = "请假信息", required = true) @Valid @RequestBody Leave leave) throws Exception {
        log.info("开始申请请假，用户ID：{}，请假类型：{}", leave.getUserId(), leave.getLeaveType());
        
        // 参数校验
        if (leave.getUserId() == null || leave.getUserId() <= 0) {
            return Result.fail("用户ID不能为空且必须大于0");
        }
        if (leave.getLeaveType() == null) {
            return Result.fail("请假类型不能为空");
        }
        if (leave.getStartDate() == null || leave.getEndDate() == null) {
            return Result.fail("请假开始日期和结束日期不能为空");
        }
        if (leave.getStartDate().isAfter(leave.getEndDate())) {
            return Result.fail("请假开始日期不能晚于结束日期");
        }
        
        Boolean result = leaveService.applyLeave(leave);
        log.info("申请请假成功，用户ID：{}，结果：{}", leave.getUserId(), result);
        return Result.success("申请成功", result);
    }

    @ApiLog(
        logTitle = "审批请假",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PostMapping("/approve/{id}")
    @Operation(summary = "审批请假", description = "审批请假")
    public Result<Boolean> approveLeave(
            @Parameter(description = "请假记录ID", required = true) @PathVariable @NotNull Long id, 
            @Parameter(description = "审批状态", required = true) @RequestParam @NotNull Integer status,
            @Parameter(description = "审批人ID", required = true) @RequestParam @NotNull Long approverId,
            @Parameter(description = "审批备注") @RequestParam(required = false) String approveRemark) throws Exception {
        log.info("开始审批请假，ID：{}，状态：{}，审批人ID：{}", id, status, approverId);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("请假记录ID必须大于0");
        }
        if (status == null) {
            return Result.fail("审批状态不能为空");
        }
        if (approverId == null || approverId <= 0) {
            return Result.fail("审批人ID必须大于0");
        }
        
        Boolean result = leaveService.approveLeave(id, status, approverId, approveRemark);
        log.info("审批请假成功，ID：{}，结果：{}", id, result);
        return Result.success("审批成功", result);
    }

    @ApiLog(
        logTitle = "撤销请假申请",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PostMapping("/cancel/{id}")
    @Operation(summary = "撤销请假申请", description = "撤销请假申请")
    public Result<Boolean> cancelLeave(
            @Parameter(description = "请假记录ID", required = true) @PathVariable @NotNull Long id, 
            @Parameter(description = "用户ID", required = true) @RequestParam @NotNull Long userId) throws Exception {
        log.info("开始撤销请假申请，ID：{}，用户ID：{}", id, userId);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("请假记录ID必须大于0");
        }
        if (userId == null || userId <= 0) {
            return Result.fail("用户ID必须大于0");
        }
        
        Boolean result = leaveService.cancelLeave(id, userId);
        log.info("撤销请假申请成功，ID：{}，结果：{}", id, result);
        return Result.success("撤销成功", result);
    }

    @GetMapping("/statistics")
    @Operation(summary = "统计请假数据", description = "统计请假数据")
    public Result<Map<String, Object>> getLeaveStatistics(
            @Parameter(description = "物业公司ID", required = true) @RequestParam @NotNull Long propertyCompanyId,
            @Parameter(description = "开始日期", required = true) @RequestParam @NotNull LocalDate startDate,
            @Parameter(description = "结束日期", required = true) @RequestParam @NotNull LocalDate endDate) throws Exception {
        log.info("开始统计请假数据，物业公司ID：{}，开始日期：{}，结束日期：{}", propertyCompanyId, startDate, endDate);
        
        // 参数校验
        if (propertyCompanyId == null || propertyCompanyId <= 0) {
            return Result.fail("物业公司ID必须大于0");
        }
        if (startDate == null || endDate == null) {
            return Result.fail("开始日期和结束日期不能为空");
        }
        if (startDate.isAfter(endDate)) {
            return Result.fail("开始日期不能晚于结束日期");
        }
        
        Map<String, Object> result = leaveService.getLeaveStatistics(propertyCompanyId, startDate, endDate);
        log.info("统计请假数据成功，物业公司ID：{}", propertyCompanyId);
        return Result.success("统计成功", result);
    }

    @ApiLog(
        logTitle = "更新请假状态",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/{id}/status")
    @Operation(summary = "更新请假状态", description = "更新请假状态")
    public Result<Boolean> updateStatus(
            @Parameter(description = "请假记录ID", required = true) @PathVariable @NotNull Long id, 
            @Parameter(description = "状态", required = true) @RequestParam @NotNull Integer status) throws Exception {
        log.info("开始更新请假状态，ID：{}，状态：{}", id, status);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("请假记录ID必须大于0");
        }
        if (status == null) {
            return Result.fail("状态不能为空");
        }
        
        Boolean result = leaveService.updateStatus(id, status, SecurityUtils.getCurrentUserId());
        log.info("更新请假状态成功，ID：{}，结果：{}", id, result);
        return Result.success("更新成功", result);
    }

    @ApiLog(
        logTitle = "删除请假记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/{id}")
    @Operation(summary = "删除请假记录", description = "删除请假记录")
    public Result<Boolean> deleteById(@Parameter(description = "请假记录ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("开始删除请假记录，ID：{}", id);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("请假记录ID必须大于0");
        }
        
        Boolean result = leaveService.deleteById(id, SecurityUtils.getCurrentUserId());
        log.info("删除请假记录成功，ID：{}，结果：{}", id, result);
        return Result.success("删除成功", result);
    }
}